from django.db import models, IntegrityError
from filedb import SimpleFileDb, FILE_DB_ROOT
from django.core.exceptions import ObjectDoesNotExist

class AccessionModel(models.Model):
    """
    Abstract class used by other accession application models.
    
    Handles file-based db stuff here with 'path' and 'path_type' attributes and overloads the 'save' method to autoset those two attributes
    
    Note that 'PATH_DEFAULT' must be set to whatever file or directory path you desire for the model's corresponding file-based db setup. 'PATH_DEFAULT' must be a string and will be rendered with django's template engine. The one variable that will be passed is 'obj' which is an instance of the current model, so you can have something like '${obj.name}' and that will render as whatever name is assigned to the current row of the model.
    
    TODO:
    - figure out how to handle deleting a db row
    """
    # File-Based Db Settings
    FILE, DIR = range(2)
    PATH_TYPE_CHOICES = (
        (FILE, 'file'),
        (DIR, 'directory')
    )
    PATH_TYPE_DEFAULT = DIR  # change this in inherited class if file
    PATH_DEFAULT = None  # change this in inherited class
    
    # Common Db Fields
    name = 'common accession'
    path = models.FilePathField(path=FILE_DB_ROOT, max_length=200, blank=True, editable=False)
    path_type = models.PositiveSmallIntegerField(choices=PATH_TYPE_CHOICES, blank=True, editable=False)
    
    def __init__(self, *args, **kwargs):
        if self.PATH_DEFAULT is None or self.PATH_TYPE_DEFAULT is None:
            raise Exception("PATH_DEFAULT and/or PATH_TYPE_DEFAULT must be set")
        self.path_type = self.PATH_TYPE_DEFAULT
        self._filedb = SimpleFileDb(self.path_type, context={'obj': self})
        super(AccessionModel, self).__init__(*args, **kwargs)
    
    def __unicode__(self):
        return self.name
    
    def _setup_path(self):
        """
        Empty function that can be extended to do additional operations
        when a new path is created
        """
        pass
    
    def clean(self, *args, **kwargs):
        """
        Autoset the path to a corresponding file or directory
        based on 'PATH_DEFAULT' and 'PATH_TYPE_DEFAULT'.
        
        Overloads 'clean' method.
        """
        self.path_type = self.PATH_TYPE_DEFAULT
        if self.pk is not None: # row already exists since it has a primary key
            try:
                old_instance = self.__class__.objects.get(pk=self.pk)
                self._filedb.setPath(old_instance.path)
            except ObjectDoesNotExist:  # just in case, catch an exception if row already exists
                pass
        self.path = self._filedb.updatePath(self.PATH_DEFAULT)
        self._filedb.check()
        super(AccessionModel, self).clean(*args, **kwargs)
    
    def save(self, *args, **kwargs):
        """
        Overloaded save method that adds file-based db functionality
        """
        super(AccessionModel, self).save(*args, **kwargs)
        self._filedb.save(self)
        if self._filedb.is_new:
            self._setup_path()
    
    class Meta:
        abstract = True
    

